package cn.yangliu.nacos.management.service.oauth2.impl;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static cn.yangliu.nacos.management.constant.CacheConstants.GATEWAY_AUTHORITY_CACHE;

import cn.yangliu.jpa.base.service.impl.JpaServiceImpl;
import cn.yangliu.nacos.comm.enums.GlobalResultCode;
import cn.yangliu.nacos.comm.ex.GlobalException;
import cn.yangliu.nacos.management.entity.oauth2.Oauth2Client;
import cn.yangliu.nacos.management.entity.oauth2.Oauth2Role;
import cn.yangliu.nacos.management.model.ClientInsertModel;
import cn.yangliu.nacos.management.model.ClientUpdateModel;
import cn.yangliu.nacos.management.repository.oauth2.Oauth2Client2RoleRepository;
import cn.yangliu.nacos.management.repository.oauth2.Oauth2ClientRepository;
import cn.yangliu.nacos.management.repository.oauth2.Oauth2RoleRepository;
import cn.yangliu.nacos.management.service.oauth2.Oauth2ClientService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * The type of nacos.
 *
 * @author 问道于盲
 * @date 2020 -01-01
 */
@Service
@Transactional(rollbackFor = Throwable.class)
public class Oauth2ClientServiceImpl
        extends JpaServiceImpl<Oauth2Client, Long, Oauth2ClientRepository>
        implements Oauth2ClientService {

    /**
     * current class instance's member.
     * The Role repository.
     */
    @Autowired
    private Oauth2RoleRepository roleRepository;

    /**
     * current class instance's member.
     * The Client 2 role repository.
     */
    @Autowired
    private Oauth2Client2RoleRepository client2RoleRepository;

    /**
     * Insert oauth 2 client.
     *
     * @param model the model
     * @return the oauth 2 client
     */
    @Override
    @CacheEvict(cacheNames = GATEWAY_AUTHORITY_CACHE, allEntries = true)
    public Oauth2Client insert(ClientInsertModel model) {
        Oauth2Client client = new Oauth2Client();
        client.setClientId(UUID.randomUUID().toString());
        client.setClientSecret(UUID.randomUUID().toString());
        BeanUtils.copyProperties(model, client);
        storeRole(client, model.getRoleIds());
        return repository.save(client);
    }

    /**
     * Update oauth 2 client.
     *
     * @param model the model
     * @return the oauth 2 client
     */
    @Override
    @CacheEvict(cacheNames = GATEWAY_AUTHORITY_CACHE, allEntries = true)
    public Oauth2Client update(ClientUpdateModel model) {
        Optional<Oauth2Client> optional = repository.findById(model.getId());
        if (!optional.isPresent()) {
         throw new GlobalException(GlobalResultCode.DATA_NOT_EXIST);
        }
        Oauth2Client client = optional.get();
        BeanUtils.copyProperties(model, client);
        storeRole(client, model.getRoleIds());
        return repository.save(client);
    }

    /**
     * Store role.
     *
     * @param client  the client
     * @param roleIds the role ids
     */
    private void storeRole(Oauth2Client client, List<Long> roleIds) {
        if(CollectionUtils.isEmpty(roleIds)) {
           return;
        }
        List<Oauth2Role> roles = roleRepository.findAllById(roleIds);
        client.setRoles(roles);
    }

    /**
     * Delete by id.
     *
     * @param id the id
     */
    @Override
    @CacheEvict(cacheNames = GATEWAY_AUTHORITY_CACHE, allEntries = true)
    public void deleteById(Long id) {
        client2RoleRepository.deleteByClientId(id);
        super.deleteById(id);
    }
}
